/* include fig01 */
#include	"unp.h"
#include	"client.h"

int main(int argc, char **argv) {
	int i, maxi, maxfd, listenfd, connfd, sockfd;
	int nready, client[FD_SETSIZE];
	ssize_t n;
	fd_set rset, allset;
	char buf[MAXLINE];
	socklen_t clilen;
	struct sockaddr_in cliaddr, servaddr;
	const int on = 1; /*bind error prevention*/
	Client *cli;
	int cmdNum = 0;

	listenfd = Socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(SERV_PORT);

	Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); /*bind error prevention*/

	Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

	Listen(listenfd, LISTENQ);

	maxfd = listenfd; /* initialize */
	maxi = -1; /* index into client[] array */
	for (i = 0; i < FD_SETSIZE; i++)
		client[i] = -1; /* -1 indicates available entry */
	FD_ZERO(&allset);
	FD_SET(listenfd, &allset);
	fprintf(stderr, "Wait for readable sockets : [3%s]\n", buf);
	/* end fig01 */

	/* include fig02 */
	for (;;) {
		rset = allset; /* structure assignment */
		nready = Select(maxfd + 1, &rset, NULL, NULL, NULL);

		if (FD_ISSET(listenfd, &rset)) { /* new client connection */
			clilen = sizeof(cliaddr);
			connfd = Accept(listenfd, (SA *) &cliaddr, &clilen); /* wait */
 #ifdef NOTDEF
			printf("Client('%s', %d\n) connected",
					Inet_ntop(AF_INET, &cliaddr.sin_addr, 4, NULL),
					ntohs(cliaddr.sin_port));
 #endif

			for (i = 0; i < FD_SETSIZE; i++)
				if (client[i] < 0) {
					client[i] = connfd; /* save descriptor */
					cli = createClient(connfd);
					break;
				}
			if (i == FD_SETSIZE)
				err_quit("too many clients");

			memset(buf, 0x00, MAXLINE);
			for(cli = getClientList(); cli != NULL; cli = cli->next){
				sprintf(buf, "%s, %d", buf, cli->connfd);
			}
			fprintf(stderr, "Wait for readable sockets : [3%s]\n", buf);

			FD_SET(connfd, &allset); /* add new descriptor to set */
			if (connfd > maxfd)
				maxfd = connfd; /* for select */
			if (i > maxi)
				maxi = i; /* max index in client[] array */

			if (--nready <= 0)
				continue; /* no more readable descriptors */
		}

		for (i = 0; i <= maxi; i++) { /* check all clients for data */
			if ((sockfd = client[i]) < 0)
				continue;
			if (FD_ISSET(sockfd, &rset)) {
				cli = getClient(sockfd);
				if ((n = Read(cli->connfd, cli->buf, MAXLINE)) == 0) {
					/*4connection closed by client */
					Close(sockfd);
					FD_CLR(sockfd, &allset);
//					destoryClient(cli);
					client[i] = -1;
				} else {
					cmdNum = serverCommand(cli, cli->buf);
					responseCommand(cli, cmdNum);
					if (cmdNum == 3) {
						Close(cli->connfd);
						FD_CLR(cli->connfd, &allset);
						destroyClient(cli);
						break;
					}
					fprintf(stderr, "Wait for readable sockets : [3%s]\n", buf);
				}

				if (--nready <= 0)
					break; /* no more readable descriptors */
			}
		}
	}
}
/* end fig02 */
